﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json.Linq;

namespace LdCms.Web.Controllers.API.Basics.V1
{
    using LdCms.Common.Extension;
    using LdCms.Common.Image;
    using LdCms.Common.Json;
    using LdCms.Common.Security;
    using LdCms.Common.Utility;
    using LdCms.EF.DbModels;
    using LdCms.IBLL.Basics;
    using LdCms.IBLL.Member;
    using LdCms.IBLL.Sys;
    using LdCms.Web.Services;

    /// <summary>
    /// 基础公共部分
    /// 文件上传接口：
    ///     1、单个文件上传
    ///        http请求方式: POST
    ///        请求内容类型:contentType: "multipart/form-data"
    ///        URL：cgi/v3/basics/upload/file/single?access_token=access_token
    ///     2、批量多个文件上传
    ///        http请求方式: POST
    ///        请求内容类型:contentType: "multipart/form-data"
    ///        URL：cgi/v3/basics/upload/file/batch?access_token=access_token
    ///     2、图片Base64String上传
    ///        http请求方式: POST
    ///        请求内容类型:contentType: "application/json"
    ///        URL：cgi/v3/basics/upload/image/code?access_token=access_token
    ///        POST：{"base64":""}
    /// 
    /// 
    /// </summary>
    [ApiVersion("1.0")]
    [ControllerName("basics/upload")]
    public class BasicsUploadController : BaseApiController
    {
        private readonly IBaseApiManager BaseApiManager;
        private readonly IHttpContextAccessor Accessor;
        private readonly IConfigService ConfigService;
        private readonly IAccountService AccountService;
        private readonly IMediaService MediaService;
        public BasicsUploadController(IBaseApiManager BaseApiManager, IHttpContextAccessor Accessor, IConfigService ConfigService, IAccountService AccountService, IMediaService MediaService) : base(BaseApiManager)
        {
            this.BaseApiManager = BaseApiManager;
            this.Accessor = Accessor;
            this.ConfigService = ConfigService;
            this.AccountService = AccountService;
            this.MediaService = MediaService;
        }

        [HttpPost]
        [ActionName("file/single")]
        public IActionResult SaveFileSingle(string access_token)
        {
            long logId = 0;
            try
            {
                logId = BaseApiManager.SaveLogs(access_token);

                var files = Request.Form.Files;
                int count = files.Count;
                long size = files.Sum(f => f.Length);
                if (count == 0)
                    return Error(logId, "上传文件不能为空！");
                if (size == 0)
                    return Error(logId, "上传文件大小不能为0字节！");

                var formFile = files.FirstOrDefault();
                var name = formFile.Name;
                var fileSize = formFile.Length;
                var fileName = formFile.FileName;
                string uploadPath = CreateUploadPath(MemberAccount.SystemID, MemberAccount.CompanyID, fileName);
                string newFileName = CreateFileName(fileName);
                var filePath = string.Format("{0}\\{1}", uploadPath, newFileName);
                string src = ToRelativePath(filePath);
                string url = ToAbsoluteUri(filePath);
                string mediaId = PrimaryKeyHelper.MakePrimaryKey(PrimaryKeyHelper.PrimaryKeyType.BasicsMedia);
                var media = new Ld_Basics_Media()
                {
                    SystemID = MemberAccount.SystemID,
                    CompanyID = MemberAccount.CompanyID,
                    MediaID = mediaId,
                    FileName = fileName,
                    FileExtension = Path.GetExtension(fileName).ToLower(),
                    FileSize = fileSize,
                    Url = url,
                    Src = src,
                };
                var data = new { mediaid = mediaId, name = fileName, size = fileSize, url, src };
                if (formFile.Length > 0)
                {
                    using (var stream = new FileStream(filePath, FileMode.Create))
                    {
                        formFile.CopyTo(stream);
                        stream.Flush();
                    }
                }
                int result = MediaService.SaveMediaMember(MemberAccount.MemberID, media);
                if (result > 0)
                    return Success(logId, "ok", new { count, size, file = data });
                else
                    return Error(logId, "upload fail！");
            }
            catch (Exception ex)
            {
                return Error(logId, ex.Message);
            }
        }
        [HttpPost]
        [ActionName("file/batch")]
        public IActionResult SaveFileBatch(string access_token)
        {
            long logId = 0;
            try
            {
                logId = BaseApiManager.SaveLogs(access_token);

                var files = Request.Form.Files;
                int count = files.Count;
                long size = files.Sum(f => f.Length);
                if (count == 0)
                    return Error(logId, "上传文件不能为空！");
                if (size == 0)
                    return Error(logId, "上传文件大小不能为0字节！");

                List<object> lists = new List<object>();
                List<Ld_Basics_Media> media = new List<Ld_Basics_Media>();
                foreach (var formFile in files)
                {
                    var name = formFile.Name;
                    var fileSize = formFile.Length;
                    var fileName = formFile.FileName;
                    string uploadPath= CreateUploadPath(MemberAccount.SystemID, MemberAccount.CompanyID, fileName);
                    string newFileName = CreateFileName(fileName);
                    var filePath = string.Format("{0}\\{1}", uploadPath, newFileName);
                    string src = ToRelativePath(filePath);
                    string url = ToAbsoluteUri(filePath);
                    string mediaId = PrimaryKeyHelper.MakePrimaryKey(PrimaryKeyHelper.PrimaryKeyType.BasicsMedia);
                    media.Add(new Ld_Basics_Media()
                    {
                        SystemID = MemberAccount.SystemID,
                        CompanyID = MemberAccount.CompanyID,
                        MediaID = mediaId,
                        FileName = fileName,
                        FileExtension = Path.GetExtension(fileName).ToLower(),
                        FileSize = fileSize,
                        Url = url,
                        Src = src,
                    });
                    lists.Add(new { mediaid = mediaId, name = fileName, size = fileSize, url, src });
                    if (formFile.Length > 0)
                    {
                        using (var stream = new FileStream(filePath, FileMode.Create))
                        {
                            formFile.CopyTo(stream);
                            stream.Flush();
                        }
                    }
                }
                int result = MediaService.SaveMediaMember(MemberAccount.MemberID, media);
                if (result > 0)
                    return Success(logId,"ok", new { count, size, file = lists });
                else
                    return Error(logId, "upload fail！");
            }
            catch (Exception ex)
            {
                return Error(logId, ex.Message);
            }
        }
        [HttpPost]
        [ActionName("image/code")]
        public IActionResult SaveImageCode(string access_token, [FromBody]JObject formValue)
        {
            long logId = 0;
            try
            {
                logId = BaseApiManager.SaveLogs(access_token);
                //string base64String = Accessor.HttpContext.Request.GetInputStream();
                string base64String = GetJObjectValue(formValue, "base64");
                string imageCode = ImageHelper.GetImageCode(base64String);
                long fileSize = imageCode.Length;
                string fileName = string.Format("{0}.{1}", GeneralCodeHelper.GetRandomInt(8), ImageHelper.GetImageExtension(base64String));
                string uploadPath = CreateUploadPath(MemberAccount.SystemID, MemberAccount.CompanyID, fileName);
                string newFileName = CreateFileName(fileName);
                var filePath = string.Format("{0}\\{1}", uploadPath, newFileName);
                string src = ToRelativePath(filePath);
                string url = ToAbsoluteUri(filePath);
                string mediaId = PrimaryKeyHelper.MakePrimaryKey(PrimaryKeyHelper.PrimaryKeyType.BasicsMedia);
                var media = new Ld_Basics_Media()
                {
                    SystemID = MemberAccount.SystemID,
                    CompanyID = MemberAccount.CompanyID,
                    MediaID = mediaId,
                    FileName = fileName,
                    FileExtension = Path.GetExtension(fileName).ToLower(),
                    FileSize = fileSize,
                    Url = url,
                    Src = src,
                };
                var data = new { mediaid = mediaId, name = fileName, size = fileSize, url, src };
                if (fileSize > 0)
                {
                    string savePath = ImageHelper.Base64StringToImage(filePath, base64String);
                }
                int result = MediaService.SaveMediaMember(MemberAccount.MemberID, media);
                if (result > 0)
                    return Success(logId, "ok", new { count = 1, size = fileSize, file = data });
                else
                    return Error(logId, "upload fail！");
            }
            catch (Exception ex)
            {
                return Error(logId, ex.Message);
            }
        }

        [HttpPost]
        [ActionName("iceeditor")]
        public IActionResult SaveFileBatchByIceEditor(string access_token)
        {
            long logId = 0;
            try
            {
                logId = BaseApiManager.SaveLogs(access_token);

                var files = Request.Form.Files;
                int count = files.Count;
                long size = files.Sum(f => f.Length);
                if (count == 0)
                    return Error(logId, "上传文件不能为空！");
                if (size == 0)
                    return Error(logId, "上传文件大小不能为0字节！");

                List<object> lists = new List<object>();
                List<Ld_Basics_Media> media = new List<Ld_Basics_Media>();
                foreach (var formFile in files)
                {
                    var name = formFile.Name;
                    var fileSize = formFile.Length;
                    var fileName = formFile.FileName;
                    string uploadPath = CreateUploadPath(MemberAccount.SystemID, MemberAccount.CompanyID, fileName);
                    string newFileName = CreateFileName(fileName);
                    var filePath = string.Format("{0}\\{1}", uploadPath, newFileName);
                    string src = ToRelativePath(filePath);
                    string url = ToAbsoluteUri(filePath);
                    string mediaId = PrimaryKeyHelper.MakePrimaryKey(PrimaryKeyHelper.PrimaryKeyType.BasicsMedia);
                    media.Add(new Ld_Basics_Media()
                    {
                        SystemID = MemberAccount.SystemID,
                        CompanyID = MemberAccount.CompanyID,
                        MediaID = mediaId,
                        FileName = fileName,
                        FileExtension = Path.GetExtension(fileName).ToLower(),
                        FileSize = fileSize,
                        Url = url,
                        Src = src,
                    });
                    lists.Add(new { mediaid = mediaId, name = fileName, size = fileSize, url, src });
                    if (formFile.Length > 0)
                    {
                        using (var stream = new FileStream(filePath, FileMode.Create))
                        {
                            formFile.CopyTo(stream);
                            stream.Flush();
                        }
                    }
                }
                int result = MediaService.SaveMediaMember(MemberAccount.MemberID, media);
                if (result > 0)
                {
                    List<object> successResult = new List<object>();
                    foreach (var m in lists)
                    {
                        successResult.Add(new { url = m.GetObjectValues("url"), name = m.GetObjectValues("name"), error = 0 });
                    }
                    return Result(logId, successResult.ToJson());
                }
                else
                {
                    List<object> failResult = new List<object>();
                    failResult.Add(new { error = "upload fail！" });
                    return Result(logId, failResult.ToJson());
                }
            }
            catch (Exception ex)
            {
                List<object> lists = new List<object>();
                lists.Add(new { error = ex.Message });
                string result = lists.ToJson();
                return Result(logId, result);
            }
        }

        #region 私有化方法
        private string CreateUploadPath(int systemId, string companyId,string fileName)
        {
            try
            {
                string webRootPath = Utility.AppRoot();
                string UploadRootDirectory = string.Format("{0}\\{1}", webRootPath, GetUploadRootDirectory(systemId, companyId));
                if (!Directory.Exists(UploadRootDirectory))
                    Directory.CreateDirectory(UploadRootDirectory);
                string companyFolder = string.Format("{0}\\{1}", UploadRootDirectory, companyId);
                if (!Directory.Exists(companyFolder))
                    Directory.CreateDirectory(companyFolder);

                string fileCategoryFolder = "file";
                string fileExtension = Path.GetExtension(fileName);
                if (Utility.IsPic(fileName))
                    fileCategoryFolder = "image";
                if (Utility.IsOfficeFile(fileName))
                    fileCategoryFolder = "office";
                if (Utility.IsVideoFile(fileName))
                    fileCategoryFolder = "video";

                string extensionFolder = string.Format("{0}\\{1}", companyFolder, fileCategoryFolder);
                if (!Directory.Exists(extensionFolder))
                    Directory.CreateDirectory(extensionFolder);
                string dateFolder = string.Format("{0}\\{1}", extensionFolder, DateTime.Now.ToString("yyyyMMdd"));
                if (!Directory.Exists(dateFolder))
                    Directory.CreateDirectory(dateFolder);
                return dateFolder;
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
        private string CreateFileName(string fileName)
        {
            try
            {
                string timeStr = DateTime.Now.ToString("yyyyMMddHHmmss");
                string guidInt = GeneralCodeHelper.GuidTo16String();
                string fileExtension = System.IO.Path.GetExtension(fileName).ToLower();
                return string.Format("{0}_{1}{2}", timeStr, guidInt, fileExtension);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
        private string GetUploadRootDirectory(int systemId,string companyId)
        {
            try
            {
                string rootDirectory = "uploads";
                var entity = ConfigService.GetConfigPro(systemId, companyId);
                if (entity == null)
                    return rootDirectory;
                return string.IsNullOrEmpty(entity.UploadRoot) ? rootDirectory : entity.UploadRoot;
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
        private string ToRelativePath(string filePath)
        {
            try
            {
                string webRootPath = Utility.AppRoot();
                return filePath.Replace(webRootPath, "").Replace("\\", "/");
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
        private string ToAbsoluteUri(string filePath)
        {
            try
            {
                string httpWebRoot = Accessor.HttpContext.Request.GetHttpWebRoot();
                string relativePath = ToRelativePath(filePath);
                return string.Format("{0}{1}", httpWebRoot, relativePath);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
        #endregion

    }
}